<script setup lang="ts">
import { ref, watch, nextTick } from 'vue'

import { ElMessage } from 'element-plus'
import { shuffle } from 'lodash'

interface ItemType {
  index: number
  name: string | number
  status: number
}

interface Props {
  data: ItemType[]
}

const props = defineProps<Props>()

const boxRef = ref<InstanceType<typeof HTMLElement>>()
const timer = ref(-1)
let dataList = ref([] as ItemType[])
const randomIndex = ref(-1)
const boxSize = ref(0)
const levelNum = ref(0)
const realWidth = ref('100%')

/**
 * 初始化
 */
const init = () => {
  dataList.value = props.data || ([] as ItemType[])

  // 计算方块的大小间距
  nextTick(() => {
    calcBox()
  })
}

const calcBox = () => {
  const width = boxRef.value!.offsetWidth - 48
  const height = boxRef.value!.offsetHeight

  // 最小一层高
  let level = 1
  recursionFun(level, width, height)
}

const recursionFun = (level: number, width: number, height: number) => {
  // ** 通过高来定宽 **

  // 总数与层数能否整除，不能的话层数需要加一
  if (dataList.value.length % level !== 0) {
    level++
  }

  // 每层元素的尺寸大小，超过200则为200
  let _size = Math.floor((height - 8 * level) / level)
  _size = _size > 200 ? 200 : _size

  // 计算每层的个数
  let _levelNum: number
  if (dataList.value.length % level !== 0) {
    _levelNum = Math.ceil(dataList.value.length / (level - 1))
  } else {
    _levelNum = dataList.value.length / level
  }

  // 计算真实的宽度
  const _realWidth = _size * _levelNum + 8 * (_levelNum - 1)
  // 如果真实的宽度大于真实高度的三倍，则增加一层
  if (_realWidth > (_size * level + 8 * level) * 4) {
    level++
    recursionFun(level, width, height)
    return
  }

  console.info(level, _levelNum, _realWidth, width, _size, '_levelNum')

  // 真实的宽度大于屏幕的宽度，溢出，增加一层来展示
  if (_realWidth > width) {
    level++
    recursionFun(level, width, height)
    return
  }

  boxSize.value = _size
  levelNum.value = _levelNum
  realWidth.value = _realWidth + 'px'
}

watch(
  () => props.data,
  () => {
    init()
  },
  {
    immediate: true
  }
)

/**
 * 开始抽奖
 */
const playEvent = () => {
  // 清除循环器
  if (timer.value !== -1) {
    clearInterval(timer.value)
  }

  // 1.先洗牌
  shuffleEvent()

  // 2.暂停一秒后开始抽奖
  setTimeout(() => {
    // 筛选出为选中的数组
    const filterData = dataList.value.filter((item) => item.status === 0)

    // 如果只剩一个，直接选中结束
    if (filterData.length === 1) {
      randomIndex.value = dataList.value.findIndex((item) => item.index === filterData[0].index)

      pauseEvent()

      ElMessage('这是最后一个奖品啦！')
      return
    }

    // 启动循环器
    timer.value = setInterval(() => {
      // 数组的随机索引
      const _randomIndex = Math.floor(Math.random() * filterData.length)
      randomIndex.value = dataList.value.findIndex(
        (item) => item.index === filterData[_randomIndex].index
      )
    }, 220)
  }, 500)
}

/**
 * 结束抽奖
 */
const pauseEvent = () => {
  dataList.value[randomIndex.value].status = 1

  clearInterval(timer.value)
  timer.value = -1
  randomIndex.value = -1
}

/**
 * 打乱
 */
const shuffleEvent = () => {
  dataList.value = shuffle(dataList.value)
}

defineExpose({
  playEvent,
  pauseEvent,
  shuffleEvent
})
</script>

<template>
  <div
    ref="boxRef"
    :style="{
      flex: 1,
      width: realWidth
    }"
  >
    <transition-group name="cell" tag="div" class="lucky-draw-panel--lattice__wrapper">
      <div
        :style="{
          height: boxSize + 'px',
          width: boxSize + 'px',
          marginRight: (index + 1) % levelNum === 0 ? '0' : '8px'
        }"
        :class="{
          'lattice-panel__wrapper': true,
          'lattice-panel--move': randomIndex === index,
          'lattice-panel--active': item.status === 1
        }"
        v-for="(item, index) in dataList"
        :key="item.index"
      >
        {{ item.name }}
      </div>
    </transition-group>
  </div>
</template>

<style scoped lang="scss">
.lucky-draw-panel--lattice__wrapper {
  display: flex;
  flex-wrap: wrap;

  .lattice-panel__wrapper {
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid #e4e7ed;
    background-color: #fff;
    border-radius: 5%;
    box-sizing: border-box;
    margin-bottom: 8px;
    cursor: pointer;

    box-shadow:
      3px 3px 4px inset rgba(255, 255, 255, 0.6),
      -3px -3px 4px inset rgba(0, 0, 0, 0.3);
  }

  .lattice-panel__wrapper:hover:not(.lattice-panel--active),
  .lattice-panel--move {
    transition: background-color 0.3s ease;
    background-color: #d1edc4;
  }

  .lattice-panel--active {
    background-color: #95d475;
    transition: background-color 0.6s ease;
    box-shadow:
      3px 3px 4px inset rgba(255, 255, 255, 0.6),
      -3px -3px 4px inset rgba(0, 0, 0, 0.3);
  }
}

.cell-move {
  transition: transform 0.3s !important;
}
</style>
